package com.guan.system.service.sysuser.impl;

import cn.hutool.core.collection.CollectionUtil;
import cn.hutool.core.util.StrUtil;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.guan.common.core.constants.HttpConstants;
import com.guan.common.core.domain.R;
import com.guan.common.core.domain.VO.LoginUserVO;
import com.guan.common.core.enums.ResultCode;
import com.guan.common.core.enums.UserIdentity;
import com.guan.common.core.domain.LoginUser;
import com.guan.ojcommonsecurity.exception.ServiceException;
import com.guan.ojcommonsecurity.service.TokenService;
import com.guan.system.domain.sysuser.SysUser;
import com.guan.system.domain.sysuser.dto.SysUserSavaDTO;
import com.guan.system.mapper.SysUserMapper;
import com.guan.system.service.sysuser.ISysUserService;
import com.guan.system.utils.BCryptUtils;
import jakarta.annotation.Resource;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.cloud.context.config.annotation.RefreshScope;
import org.springframework.stereotype.Service;

import java.util.List;

@Service
@RefreshScope
public class SysUserServiceImpl implements ISysUserService {

    @Autowired
    private SysUserMapper sysUserMapper;

    @Value("${jwt.secret}")
    private String secret; // nacos远程配置的jwt密钥

    @Resource
    private TokenService tokenService;

    @Override
    public R<String> sysUserLogin(String userAccount, String password) {
        // 1. 通过帐号在数据库中查询，对应的用户信息
        LambdaQueryWrapper<SysUser> queryWrapper = new LambdaQueryWrapper<>();
        //SELECT password from tb_sys_user WHERE user_account = #{userAccount}
        SysUser sysUser = sysUserMapper.selectOne(queryWrapper
                .select(SysUser::getUserId, SysUser::getPassword, SysUser::getNickName)
                .eq(SysUser::getUserAccount, userAccount));

        //R<Void> loginResult = new R<>();
        if (sysUser == null) {
            return R.fail(ResultCode.FAILED_USER_NOT_EXISTS);
        }
        if (BCryptUtils.matchesPassword(password, sysUser.getPassword())) {
            String token = tokenService.creatToken(sysUser.getUserId(), sysUser.getNickName(), null ,secret, UserIdentity.ADMIN.getValue());
            return R.ok(token);
        }

        return R.fail(ResultCode.FAILED_LOGIN);
    }

    @Override
    public Integer add(SysUserSavaDTO sysUserSavaDTO) {
        // 判断用户名是否唯一
        List<SysUser> sysUserList = sysUserMapper.selectList(new LambdaQueryWrapper<SysUser>()
                .eq(SysUser::getUserAccount, sysUserSavaDTO.getUserAccount()));
        if(CollectionUtil.isNotEmpty(sysUserList)){
            // 用户已存在
            throw new ServiceException(ResultCode.AILED_USER_EXISTS);
        }
        // 将 dto 转为 实体
        SysUser sysUser = new SysUser();
        sysUser.setUserAccount(sysUserSavaDTO.getUserAccount());
        sysUser.setPassword(BCryptUtils.encryptPassword(sysUserSavaDTO.getPassword()));
        return sysUserMapper.insert(sysUser);
    }

    @Override
    public R<Void> logout(String token) {
        // 1. 校验 token 的合法性
        LoginUser loginUser = tokenService.parseToken2LoginUser(token,secret);
        if (loginUser == null || loginUser.getIdentity() != UserIdentity.ADMIN.getValue()) {
            return R.fail( ResultCode.TOKEN_PARAMS_VALIDATE); // Token 无效
        }

        // 2. 移除用户的登录状态（清除 Redis 中的 token 信息）
        boolean isRemoved = tokenService.removeToken(token,secret);
        if (!isRemoved) {
            return R.fail(ResultCode.FAILED_LOGOUT); // 登出失败
        }

        // 3. 返回成功响应
        return R.ok();
    }

    @Override
    public R<LoginUserVO> info(String token) {
        // 如果前端设置了令牌前缀，则裁剪掉前缀
        if (StrUtil.isNotEmpty(token) && token.startsWith(HttpConstants.PREFIX)) {
            token = token.replaceFirst(HttpConstants.PREFIX, StrUtil.EMPTY);
        }
        LoginUser loginUser = tokenService.parseToken2LoginUser(token,secret);
        if(loginUser == null) return R.fail();
        LoginUserVO loginUserVO = new LoginUserVO();
        loginUserVO.setNickName(loginUser.getNickName());
        return R.ok(loginUserVO);
    }
}
